package com.test45_JUC;

import java.util.concurrent.CountedCompleter;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * CountedCompleter，数量计算相关的任务
 * JDK1.8引入
 */
public class Demo30_CountedCompleter {

    public static void main(String[] args) throws Exception {
        AtomicInteger result = new AtomicInteger();  // 保存最终的计算结果
        SumTask3 task = new SumTask3(1, 100, result);
        task.addToPendingCount(1);  // 设置准备执行的任务量
        ForkJoinPool pool = new ForkJoinPool();  // 开启分支任务池
        pool.submit(task);  // 执行分支任务
        while (task.getPendingCount() != 0) {   // 有任务未执行完毕
            TimeUnit.MILLISECONDS.sleep(100);
            if (result.get() != 0) {
                System.out.println("分支任务计算结果：" + result);
                break;
            }
        }
    }
}

/**
 * 实现数据累加的计算
 */
class SumTask3 extends CountedCompleter<AtomicInteger> {
    private static final int THRESHOLD = 25;    // 分支阈值
    private int start;  // 开始计算数值
    private int end;    // 结束计算数值
    private AtomicInteger result;

    public SumTask3(int start, int end, AtomicInteger result) {
        this.start = start;
        this.end = end;
        this.result = result;
    }

    // 完成计算的处理
    @Override
    public void compute() {
        // 所有的子分支的处理，以及所有相关分支的合并处理都在此方法之中完成
        int sum = 0;
        boolean isFork = (end - start) > THRESHOLD;    // 是否需要进行分支
        if (isFork) {   // 需要开启分支
            int middle = (start + end) / 2;
            SumTask3 leftTask = new SumTask3(this.start, middle, this.result);
            SumTask3 rightTask = new SumTask3(middle + 1, this.end, this.result);
            leftTask.fork();    // 开启左分支
            rightTask.fork();   // 开启右分支
        } else {    // 计算子分支
            for (int i = start; i <= end; i++) {
                sum += i;
            }
            this.result.addAndGet(sum);  // 数据的累加
            super.tryComplete();    // 钩子的触发
        }
    }

    // 钩子触发方法
    @Override
    public void onCompletion(CountedCompleter<?> caller) {
        System.out.printf("【%s】start = %d、end = %d%n",
                Thread.currentThread().getName(), this.start, this.end);
    }
}
